package com.ruoyi.common.utils.excel;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/** Excel导出工具 */
public class ExcelExportUtil {
    // 行索引
    private int rowIndex = 0;
    // 字体集合
    private final List<Font> fontList = new ArrayList<>();
    // 样式映射表集合
    private final List<Map<String,Object>> styleMapList = new ArrayList<>();
    // Excel配置项
    private BaseExcelConfigEntity<?> config;
    // 工作本
    private Workbook workbook;
    // 工作表
    private Sheet sheet;
    // 字段匹配正则
    private final String fieldReg = "\\{\\{(.+?)\\}\\}";
    // 函数匹配正则
    private final String functionReg = "\\$\\{(.+?)\\}";
    // 分组副标题表达式
    private String groupTitleExpression;
    // 分组副尾行表达式
    private String groupEndLineExpression;
    // 合计
    private BigDecimal summaryValue;
    // 是否包含合计字段
    private boolean hasSummaryField;
    /**
     * 导出Excel
     * @param config 配置项
     * @return 下载地址
     */
    public AjaxResult export(BaseExcelConfigEntity<?> config) {
        OutputStream out = null;
        // 初始化文档
        init(config);
        // 获取标题配置
        BaseExcelConfigEntity.Row titleRow = config.getTitles();
        // 如果包含标题配置，则创建标题行
        if(titleRow != null) {
            // 创建标题行并更新行索引
            createCustomRows(titleRow);
        }
        // 创建数据行并更新索引
        createTableRows();
        // 获取尾行配置
        BaseExcelConfigEntity.Row endRow = config.getEndLines();
        // 如果包含尾行配置，则创建尾行
        if(endRow != null) {
            // 创建尾行
            BaseExcelConfigEntity.Row endLineConfig = config.getEndLines();
            if(endLineConfig != null) {
                setEndLine(endRow,endLineConfig.getCells().get(0).getCellValue().toString(),summaryValue,config.getTableData().get(0));
            }
        }
        String filename = encodingFilename(config.getFileName());
        try {
            out = new FileOutputStream(getAbsoluteFile(filename));
            workbook.write(out);
        } catch (IOException e) {
            e.printStackTrace();
            throw new CustomException("生成excel失敗");
        }
        finally
        {
            if (workbook != null)
            {
                try
                {
                    workbook.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
            if (out != null)
            {
                try
                {
                    out.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        }
        return AjaxResult.success(filename);
    }

    /**
     * 初始化
     * @param config 导出参数
     */
    private void init(BaseExcelConfigEntity config){
        this.config = config;
        // 创建Excel对象
        this.workbook = new XSSFWorkbook();
        // 创建Sheet对象
        this.sheet = workbook.createSheet(config.getSheetName());
    }

    /**
     * 创建表格数据行+副标题+尾行并更新索引
     */
    private void createTableRows() {
        this.hasSummaryField = StringUtils.isNotEmpty(config.getSummaryField());
        if(this.hasSummaryField) {
            summaryValue = new BigDecimal(0);
        }
        BaseExcelConfigEntity.Row groupTitleConfig = config.getGroupTitles();
        if(groupTitleConfig != null){
            BaseExcelConfigEntity.Row.Cell groupTitleCell = groupTitleConfig.getCells().get(0);
            groupTitleExpression = groupTitleCell.getCellValue().toString();
        }
        BaseExcelConfigEntity.Row groupEndLineConfig = config.getGroupEndLines();
        if(groupEndLineConfig != null){
            BaseExcelConfigEntity.Row.Cell groupEndLineCell = groupEndLineConfig.getCells().get(0);
            groupEndLineExpression = groupEndLineCell.getCellValue().toString();
        }
        // 创建表格组
        createTables();
    }

    /**
     * 创建表格组
     */
    private void createTables() {
        List<?> tableData = config.getTableData();
        String groupField = config.getGroupField();
        Class<?> clazz;
        if(tableData.size() > 0) {
            clazz = tableData.get(0).getClass();
        } else {
            return;
        }
        Class<?>[] interfaces = clazz.getInterfaces();
        boolean isMap = false;
        if(interfaces.length > 0){
            for (Class<?> anInterface : interfaces) {
                if(anInterface.getName().equals("java.util.Map")) {
                    isMap = true;
                    break;
                }
            }
        }
        if (isMap) {
            Map<String,?> d0 = (Map<String,?>)tableData.get(0);
            Set<String> keys = d0.keySet();
            if(StringUtils.isEmpty(groupField)){
                createTable((List<Map<String, ?>>) tableData,keys);
            } else {
                createTableGroups((List<Map<String, ?>>) tableData,keys,groupField);
            }
        } else {
            Field[] fields = clazz.getDeclaredFields();
            if(StringUtils.isEmpty(groupField)){
                createTable(tableData,fields);
            } else {
                createTableGroups(tableData,fields,groupField);
            }
        }
    }

    private <T1>void createTableGroups(List<T1> tableData, Field[] fields,String groupField){
        boolean isSorted = config.isSorted();
        // 如果表格没有排过序，则重新排序该表格
        if(!isSorted){
            String sortedClass = config.getSortedClass();
            if(StringUtils.isNotEmpty(sortedClass)){
                tableData.sort((d1,d2) -> {
                    Object v1 = ReflectUtils.invokeGetter(d1,groupField);
                    Object v2 = ReflectUtils.invokeGetter(d2,groupField);
                    return compare(v1,v2,sortedClass);
                });
            }
        }
        List<List<T1>> exportListGroups = new ArrayList<>();
        List<T1> exportListGroup = new ArrayList<>();
        exportListGroup.add(tableData.get(0));
        exportListGroups.add(exportListGroup);
        for (int i = 1; i < tableData.size(); i++) {
            T1 d2 = tableData.get(i);
            Object v1 = ReflectUtils.invokeGetter(tableData.get(i - 1),groupField);
            Object v2 = ReflectUtils.invokeGetter(d2,groupField);
            if(v1 == null && v2 == null){
                exportListGroup.add(d2);
            } else if(v1 == null || v2 == null) {
                exportListGroup = new ArrayList<>();
                exportListGroup.add(d2);
                exportListGroups.add(exportListGroup);
            } else if (v1.equals(v2)) {
                exportListGroup.add(d2);
            } else {
                exportListGroup = new ArrayList<>();
                exportListGroup.add(d2);
                exportListGroups.add(exportListGroup);
            }
        }
        for (List<T1> list : exportListGroups) {
            createTable(list,fields);
        }
    }

    private void createTableGroups(List<Map<String,?>> tableData, Set<String> keys,String groupField){
        boolean isSorted = config.isSorted();
        // 如果表格没有排过序，则重新排序该表格
        if(!isSorted){
            String sortedClass = config.getSortedClass();
            if(StringUtils.isNotEmpty(sortedClass)){
                tableData.sort((d1,d2) -> {
                    Object v1 = ReflectUtils.invokeGetter(d1,groupField);
                    Object v2 = ReflectUtils.invokeGetter(d2,groupField);
                    return compare(v1,v2,sortedClass);
                });
            }
        }
        List<List<Map<String,?>>> exportListGroups = new ArrayList<>();
        List<Map<String,?>> exportListGroup = new ArrayList<>();
        exportListGroup.add(tableData.get(0));
        exportListGroups.add(exportListGroup);
        for (int i = 1; i < tableData.size(); i++) {
            Map<String,?> d2 = tableData.get(i);
            Object v1 = ReflectUtils.invokeGetter(tableData.get(i - 1),groupField);
            Object v2 = ReflectUtils.invokeGetter(d2,groupField);
            if(v1 == null && v2 == null){
                exportListGroup.add(d2);
            } else if(v1 == null || v2 == null) {
                exportListGroup = new ArrayList<>();
                exportListGroup.add(d2);
                exportListGroups.add(exportListGroup);
            } else if (v1.equals(v2)) {
                exportListGroup.add(d2);
            } else {
                exportListGroup = new ArrayList<>();
                exportListGroup.add(d2);
                exportListGroups.add(exportListGroup);
            }
        }
        for (List<Map<String,?>> list : exportListGroups) {
            createTable(list,keys);
        }
    }

    /**
     * 排序函数，比较两个值的大小
     * @param v1 前值
     * @param v2 后值
     * @param sortedClass 排序依据
     * @return 正值则为前大后小，负值则为前小后大，0则相等
     */
    private int compare(Object v1,Object v2,String sortedClass) {
        if(v1 == null || v2 == null) {
            return -1;
        }
        switch (sortedClass) {
            case "String":
                return ((String)v1).compareTo((String)v2);
            case "Integer":
                return ((Integer)v1).compareTo((Integer)v2);
            case "Long":
                return ((Long)v1).compareTo((Long)v2);
            case "Date":
                return ((Date)v1).compareTo((Date)v2);
        }
        return -1;
    }

    /**
     * 创建表格并更新索引
     * @param tableData 单组表格数据
     * @param fields 表格泛型字段
     */
    private void createTable(List<?> tableData, Field[] fields){
        // 获取分组副标题配置
        BaseExcelConfigEntity.Row groupTitleConfig = config.getGroupTitles();
        // 有分组副标题配置则创建标题行
        if(groupTitleConfig != null){
            BaseExcelConfigEntity.Row.Cell groupTitleCell = groupTitleConfig.getCells().get(0);
            String expression = parseExpression(this.fieldReg, groupTitleExpression, tableData.get(0));
            groupTitleCell.setCellValue(expression);
            createCustomRows(groupTitleConfig);
        }
        // 创建表头行
        Row headerRow = sheet.createRow(rowIndex);
        int ignoreCount = 0;
        for (int i = 0; i < fields.length; i++) {
            fields[i].setAccessible(true);
            Excel attr = fields[i].getAnnotation(Excel.class);
            if(attr == null) {
                ignoreCount++;
                continue;
            }
            // 创建单元格对象
            Cell cell = headerRow.createCell(i - ignoreCount);
            BaseExcelConfigEntity.Row.Cell headerConfig = config.getHeader();
            if(headerConfig == null) {
                headerConfig = new BaseExcelConfigEntity.Row.Cell();
                headerConfig.setBorderBottom(true);
                headerConfig.setBorderLeft(true);
                headerConfig.setBorderTop(true);
                headerConfig.setBorderRight(true);
                headerConfig.setWidth(attr.width());
            } else {
                if(headerConfig.getWidth() == 0) {
                    headerConfig.setWidth(attr.width());
                }
            }
            headerConfig.setCellValue(attr.name());
            setCellValueWithStyle(cell,headerConfig);
            //列宽*256理解为固定写法
            sheet.setColumnWidth(i - ignoreCount,(int) ((attr.width() + 0.72) * 256));
        }
        rowIndex++;
        BigDecimal tempSummaryValue = null;
        if(this.hasSummaryField){
            tempSummaryValue = new BigDecimal(0);
        }
        for (Object tableDatum : tableData) {
            if(this.hasSummaryField){
                String summaryItem = ReflectUtils.invokeGetter(tableDatum,config.getSummaryField()).toString();
                summaryValue = summaryValue.add(new BigDecimal(summaryItem));
                tempSummaryValue = tempSummaryValue.add(new BigDecimal(summaryItem));
            }
            //创建数据行
            Row dataRow = sheet.createRow(rowIndex);
            ignoreCount = 0;
            for (int j = 0; j < fields.length; j++) {
                Excel attr = fields[j].getAnnotation(Excel.class);
                if (attr == null) {
                    ignoreCount++;
                    continue;
                }
                //5.创建单元格对象(索引从0开始)
                Cell cell = dataRow.createCell(j - ignoreCount);
                Object cellValue;
                try {
                    cellValue = fields[j].get(tableDatum);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    throw new CustomException("导出excel异常");
                }
                BaseExcelConfigEntity.Row.Cell dataConfig = config.getDataCell();
                if (dataConfig == null) {
                    dataConfig = new BaseExcelConfigEntity.Row.Cell();
                    dataConfig.setBorderBottom(true);
                    dataConfig.setBorderLeft(true);
                    dataConfig.setBorderTop(true);
                    dataConfig.setBorderRight(true);
                }
                if (fields[j].getType().getName().equals(Date.class.getName())) {
                    dataConfig.setDateFormat(attr.dateFormat());
                }
                float height = dataConfig.getHeight();
                if(height > 0) {
                    dataRow.setHeight((short) (height * 20));
                }
                dataConfig.setCellValue(cellValue);
                setCellValueWithStyle(cell, dataConfig);
            }
            rowIndex++;
        }
        // 获取分组副尾行配置
        BaseExcelConfigEntity.Row groupEndLineConfig = config.getGroupEndLines();
        // 有分组副尾行配置则创建标题行
        if(groupEndLineConfig != null){
            setEndLine(groupEndLineConfig,groupEndLineExpression,tempSummaryValue,tableData.get(0));
        }
    }
    /**
     * 创建表格并更新索引
     * @param tableData 单组表格数据
     * @param keys Map键集合
     */
    private void createTable(List<Map<String,?>> tableData, Set<String> keys){
        // 获取分组副标题配置
        BaseExcelConfigEntity.Row groupTitleConfig = config.getGroupTitles();
        // 有分组副标题配置则创建标题行
        if(groupTitleConfig != null){
            BaseExcelConfigEntity.Row.Cell groupTitleCell = groupTitleConfig.getCells().get(0);
            String expression = parseExpression(this.fieldReg, groupTitleExpression, tableData.get(0));
            groupTitleCell.setCellValue(expression);
            createCustomRows(groupTitleConfig);
        }
        // 创建表头行
        Row headerRow = sheet.createRow(rowIndex);
        int colIndex = 0;
        for (String key : keys) {
            // 创建单元格对象
            Cell cell = headerRow.createCell(colIndex);
            BaseExcelConfigEntity.Row.Cell headerConfig = config.getHeader();
            if(headerConfig == null) {
                headerConfig = new BaseExcelConfigEntity.Row.Cell();
                headerConfig.setBorderBottom(true);
                headerConfig.setBorderLeft(true);
                headerConfig.setBorderTop(true);
                headerConfig.setBorderRight(true);
            } else {
                Map<String,Double> columnWidthMap = config.getColumnWidthMap();
                if(columnWidthMap == null) {
                    if(headerConfig.getWidth() == 0) {
                        headerConfig.setWidth(12);
                    }
                } else {
                    Double width = columnWidthMap.get(key);
                    if(width == null || width == 0) {
                        headerConfig.setWidth(12);
                    } else {
                        headerConfig.setWidth(width);
                    }
                }
            }
            headerConfig.setCellValue(key);
            setCellValueWithStyle(cell,headerConfig);
            //列宽*256理解为固定写法
            sheet.setColumnWidth(colIndex,(int) ((headerConfig.getWidth() + 0.72) * 256));
            colIndex++;
        }
        rowIndex++;
        BigDecimal tempSummaryValue = null;
        if(this.hasSummaryField){
            tempSummaryValue = new BigDecimal(0);
        }
        for (Map<String,?> tableDatum : tableData) {
            if(this.hasSummaryField){
                String summaryItem = tableDatum.get(config.getSummaryField()).toString();
                summaryValue = summaryValue.add(new BigDecimal(summaryItem));
                tempSummaryValue = tempSummaryValue.add(new BigDecimal(summaryItem));
            }
            //创建数据行
            Row dataRow = sheet.createRow(rowIndex);
            colIndex = 0;
            for (String key : keys) {
                //5.创建单元格对象(索引从0开始)
                Cell cell = dataRow.createCell(colIndex);
                Object cellValue = tableDatum.get(key);
                BaseExcelConfigEntity.Row.Cell dataConfig = config.getDataCell();
                if (dataConfig == null) {
                    dataConfig = new BaseExcelConfigEntity.Row.Cell();
                    dataConfig.setBorderBottom(true);
                    dataConfig.setBorderLeft(true);
                    dataConfig.setBorderTop(true);
                    dataConfig.setBorderRight(true);
                }
                if(cellValue != null && cellValue.getClass().getName().equals(Date.class.getName())) {
                    dataConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
                }
                dataRow.setHeight((short) (dataConfig.getHeight() * 20));
                dataConfig.setCellValue(cellValue);
                setCellValueWithStyle(cell, dataConfig);
                colIndex++;
            }
            rowIndex++;
        }
        // 获取分组副尾行配置
        BaseExcelConfigEntity.Row groupEndLineConfig = config.getGroupEndLines();
        // 有分组副尾行配置则创建标题行
        if(groupEndLineConfig != null){
            setEndLine(groupEndLineConfig,groupEndLineExpression,tempSummaryValue,tableData.get(0));
        }
    }

    private void setEndLine(BaseExcelConfigEntity.Row rowConfig,String lineExpression,BigDecimal summaryValue,Object data) {
        BaseExcelConfigEntity.Row.Cell groupEndLineCell = rowConfig.getCells().get(0);
        String expression = parseExpression(this.fieldReg,lineExpression,data);
        List<String> regParams = getRegParams(this.functionReg,expression);
        for (String regParam : regParams) {
            Map<String,String> functionRegMap = new HashMap<>();
            if ("summary".equals(regParam)) {
                functionRegMap.put(regParam, summaryValue.toPlainString());
                expression = parseExpression(this.functionReg, expression, functionRegMap);
            }
        }
        groupEndLineCell.setCellValue(expression);
        createCustomRows(rowConfig);
    }

    /**
     * 创建自定义行并更新索引
     * @param rowConfig 自定义行配置
     */
    private void createCustomRows(BaseExcelConfigEntity.Row rowConfig) {
        List<BaseExcelConfigEntity.Row.Cell> cellConfigs = rowConfig.getCells();
        if(cellConfigs == null || cellConfigs.size() == 0) {
            return;
        }
        // 创建标题行集合
        List<Row> titleRows = new ArrayList<>();
        // 列索引
        int colIndex = 0;
        for (BaseExcelConfigEntity.Row.Cell cellConfig : cellConfigs) {
            // 如果该标题行与上一行合并，则不更新行索引
            Cell cell;
            if (cellConfig.isJoinWithLastRow()) {
                // 创建单元格对象
                cell = titleRows.get(titleRows.size() - 1).createCell(colIndex);
                // 获取单元格所占列数
                int horizontalCellCount = cellConfig.getHorizontalCellCount();
                if (horizontalCellCount > 1) {
                    mergeRegion(rowIndex - 1, rowIndex - 1, colIndex, horizontalCellCount + colIndex - 1);
                }
                // 更新列索引
                colIndex += horizontalCellCount;
                setCellValueWithStyle(cell, cellConfig);
            } else {
                colIndex = 0;
                // 创建一行标题
                Row titleRow = sheet.createRow(rowIndex);
                // 将该标题行添加至标题行集合中
                titleRows.add(titleRow);
                // 设置行高和列宽
                titleRow.setHeight((short) (rowConfig.getHeight() * 20));
                // 创建单元格对象
                cell = titleRow.createCell(colIndex);
                // 获取单元格所占列数
                int horizontalCellCount = cellConfig.getHorizontalCellCount();
                if (horizontalCellCount > 1) {
                    mergeRegion(rowIndex, rowIndex, colIndex, horizontalCellCount - 1);
                }
                // 更新列索引
                colIndex += horizontalCellCount;
                setCellValueWithStyle(cell, cellConfig);
                // 更新行索引
                rowIndex++;
            }
        }
    }

    /**
     * 合并单元格
     * @param firstRow 首行索引
     * @param lastRow 尾行索引
     * @param firstCol 首列索引
     * @param lastCol 尾列索引
     */
    private void mergeRegion(int firstRow, int lastRow, int firstCol, int lastCol) {
        CellRangeAddress region = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
        sheet.addMergedRegion(region);
    }

    /**
     * 设置单元格内容并设置样式
     * @param cell 单元格对象
     * @param cellConfig 单元格配置项
     */
    private void setCellValueWithStyle(Cell cell,BaseExcelConfigEntity.Row.Cell cellConfig) {
        // 创建样式
        CellStyle style = getStyle(cellConfig);
        Object cellValue = cellConfig.getCellValue();
        if(cellValue == null) {
            cell.setCellValue("");
        } else if(cellValue.getClass() == Date.class) {
            // 获取日期转换格式
            String dateFormat = cellConfig.getDateFormat();
            if(StringUtils.isEmpty(dateFormat)) {
                dateFormat = "yyyy/MM/dd HH:mm:ss";
            }
            cell.setCellValue(DateUtils.parseDateToStr(dateFormat,(Date)cellValue));
        } else {
            cell.setCellValue(cellValue.toString());
        }
        cell.setCellStyle(style);
    }

    /**
     * 获取单元格样式
     * @param cellConfig 单元格参数配置
     * @return 现有样式或者新建样式
     */
    private CellStyle getStyle(BaseExcelConfigEntity.Row.Cell cellConfig){
        // 获取字体
        Font font = getFont(cellConfig);
        // 创建样式
        CellStyle style = null;
        // 获取配置项中的样式属性
        // 横向对齐方式
        String horizontalAlignmentConfig = cellConfig.getHorizontalAlignment();
        // 纵向对齐方式
        String verticalAlignmentConfig = cellConfig.getVerticalAlignment();
        // 单元格背景色
        String backgroundColorConfig = cellConfig.getBackgroundColor();
        // 上细线
        boolean borderTop = cellConfig.isBorderTop();
        // 下细线
        boolean borderBottom = cellConfig.isBorderBottom();
        // 左细线
        boolean borderLeft = cellConfig.isBorderLeft();
        // 右细线
        boolean borderRight = cellConfig.isBorderRight();
        // 判断是否没有该样式
        boolean soSuchStyle = true;
        // 遍历样式映射表集合，判断是否具有与配置项中属性完全相同的样式
        for (Map<String, Object> styleMap : styleMapList) {
            // 如果存在，则直接返回该样式
            if(styleMap.get("font").equals(font)
                    && styleMap.get("horizontalAlignment").equals(horizontalAlignmentConfig)
                    && styleMap.get("verticalAlignment").equals(verticalAlignmentConfig)
                    && styleMap.get("backgroundColor").equals(backgroundColorConfig)
                    && styleMap.get("borderTop").equals(borderTop)
                    && styleMap.get("borderBottom").equals(borderBottom)
                    && styleMap.get("borderLeft").equals(borderLeft)
                    && styleMap.get("borderRight").equals(borderRight)) {
                soSuchStyle = false;
                style = (CellStyle) styleMap.get("style");
                break;
            }
        }
        // 如果没有该样式，则创建该样式并将其加入样式映射表集合中
        if(soSuchStyle) {
            style = workbook.createCellStyle();
            style.setFont(font);
            style.setAlignment(getHorizontalAlignment(horizontalAlignmentConfig));
            style.setVerticalAlignment(getVerticalAlignment(verticalAlignmentConfig));
            style.setFillForegroundColor(getColor(backgroundColorConfig));
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            style.setWrapText(true);
            if(borderTop) {
                style.setBorderTop(BorderStyle.THIN);
            }
            if(borderBottom) {
                style.setBorderBottom(BorderStyle.THIN);
            }
            if(borderLeft) {
                style.setBorderLeft(BorderStyle.THIN);
            }
            if(borderRight) {
                style.setBorderRight(BorderStyle.THIN);
            }
            Map<String,Object> map = new HashMap<>();
            map.put("font",font);
            map.put("horizontalAlignment",horizontalAlignmentConfig);
            map.put("verticalAlignment",verticalAlignmentConfig);
            map.put("backgroundColor",backgroundColorConfig);
            map.put("borderTop",borderTop);
            map.put("borderBottom",borderBottom);
            map.put("borderLeft",borderLeft);
            map.put("borderRight",borderRight);
            map.put("style",style);
            styleMapList.add(map);
        }
        return style;
    }

    /**
     * 获取字体
     * @param cellConfig 单元格参数配置
     * @return 现有字体或者新建字体
     */
    private Font getFont(BaseExcelConfigEntity.Row.Cell cellConfig){
        // 创建字体
        Font font = null;
        // 获取配置项中的字体属性
        // 字体大小
        short fontSizeConfig = cellConfig.getFontSize();
        // 字体名称
        String fontFamilyConfig = cellConfig.getFontFamily();
        // 字体颜色
        short fontColor = getColor(cellConfig.getFontColor());
        // 判断是否没有该字体
        boolean soSuchFont = true;
        // 遍历字体集合，判断是否具有与配置项中属性完全相同的字体
        for (Font fontExist : fontList) {
            if(fontExist.getFontName().equals(fontFamilyConfig) && fontExist.getFontHeightInPoints() == fontSizeConfig && fontExist.getColor() == fontColor) {
                soSuchFont = false;
                font = fontExist;
            }
        }
        // 如果没有该字体，则创建该字体并将其加入字体集合中
        if(soSuchFont) {
            font = workbook.createFont();
            font.setFontName(fontFamilyConfig);
            font.setFontHeightInPoints(fontSizeConfig);
            font.setColor(fontColor);
            fontList.add(font);
        }
        return font;
    }

    /**
     * 获取水平对齐方式枚举
     * @param horizontalAlignment 水平对齐方式字符串
     * @return 水平对齐方式枚举
     */
    private static HorizontalAlignment getHorizontalAlignment(String horizontalAlignment) {
        if(StringUtils.isEmpty(horizontalAlignment)) {
            return HorizontalAlignment.CENTER;
        }
        switch (horizontalAlignment.toUpperCase()) {
            case "GENERAL":
                return HorizontalAlignment.GENERAL;
            case "LEFT":
                return HorizontalAlignment.LEFT;
            case "CENTER":
                return HorizontalAlignment.CENTER;
            case "RIGHT":
                return HorizontalAlignment.RIGHT;
            case "FILL":
                return HorizontalAlignment.FILL;
            case "JUSTIFY":
                return HorizontalAlignment.JUSTIFY;
            case "CENTER_SELECTION":
                return HorizontalAlignment.CENTER_SELECTION;
            case "DISTRIBUTED":
                return HorizontalAlignment.DISTRIBUTED;
        }
        return HorizontalAlignment.CENTER;
    }

    /**
     * 获取垂直对齐方式枚举
     * @param verticalAlignment 垂直对齐方式字符串
     * @return 垂直对齐方式枚举
     */
    private static VerticalAlignment getVerticalAlignment(String verticalAlignment) {
        if(StringUtils.isEmpty(verticalAlignment)) {
            return VerticalAlignment.CENTER;
        }
        switch (verticalAlignment.toUpperCase()) {
            case "TOP":
                return VerticalAlignment.TOP;
            case "CENTER":
                return VerticalAlignment.CENTER;
            case "BOTTOM":
                return VerticalAlignment.BOTTOM;
            case "JUSTIFY":
                return VerticalAlignment.JUSTIFY;
            case "DISTRIBUTED":
                return VerticalAlignment.DISTRIBUTED;
        }
        return VerticalAlignment.CENTER;
    }

    /**
     * 获取颜色
     */
    private static short getColor(String colorConfig){
        return IndexedColors.valueOf(colorConfig).getIndex();
    }


    /**
     * 匹配正则
     */
    public static List<String> getRegParams(String pattern, String content) {
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(content);

        List<String> result = new ArrayList<String>();
        while (m.find()) {
            result.add(m.group(1));
        }
        return result;
    }

    /**
     * 根据正则表达式将文本中的变量使用实际的数据替换成无变量的文本
     */
    public static String parseExpression(String pattern, String content, Object data) {
        boolean isMap = false;
        Class<?>[] interfaces = data.getClass().getInterfaces();
        if(interfaces.length > 0){
            for (Class<?> anInterface : interfaces) {
                if(anInterface.getName().equals("java.util.Map")) {
                    isMap = true;
                    break;
                }
            }
        }
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(content);

        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            String key = m.group(1);
            String value;
            if(isMap) {
                value = ((Map<String,String>)data).get(key);
            } else {
                value = ReflectUtils.invokeGetter(data,key);
            }
            m.appendReplacement(sb, value == null ? "" : value);
        }
        m.appendTail(sb);
        return sb.toString();
    }

    /**
     * 获取下载路径
     *
     * @param filename 文件名称
     */
    private static String getAbsoluteFile(String filename)
    {
        String downloadPath = RuoYiConfig.getDownloadPath() + filename;
        File desc = new File(downloadPath);
        if (!desc.getParentFile().exists())
        {
            desc.getParentFile().mkdirs();
        }
        return downloadPath;
    }

    /**
     * 编码文件名
     */
    private static String encodingFilename(String filename)
    {
        filename = filename + ".xlsx";
        return filename;
    }
}
